//
//  ViewController.m
//  OpenGLGame
//
//  Created by Nguyen Cong Huy on 11/8/12.
//  Copyright (c) 2012 UIT. All rights reserved.
//

#import "OpenGLViewController.h"
#include "LBGraphics.h"
#import  "OCImage.h"
#include "LBTexture.h"
#include "LBUtils.h"
#include "LBFilter.h"
#include "LBPolarPixellatePosterizeFilter.h"
#include "LBFramebuffer.h"
#include "LBSepiaFilter.h"
#include "LBEffect1Filter.h"
#include "LBEffect2Filter.h"
#include "LBEffect3Filter.h"
#include "LBEffect4Filter.h"
#include "LBEffect5Filter.h"
#include "LBEffect6Filter.h"
#include "LBEffect7Filter.h"
#include "LBEffect8Filter.h"
#include "LBEffect9Filter.h"
#include "LBGreyscaleFilter.h"
#include "LBWhiteBalanceFilter.h"
#include "LBMonoChromeFilter.h"
#include "LBSharpenFilter.h"
#include "LBBoxBlurFilter.h"
#include "LBRenderToScreenFilter.h"
#include "LBAdaptiveThresholdFilter.h"
#include "LBProFilter.h"
#include "LBVintageLowFilter.h"
#include "LBInstantEffectFilter.h"
#include "LBAnsenEffectFilter.h"
#include "LBRadialGradientFilter.h"
@interface OpenGLViewController () {
    OCImage* ocImg;
    LBTexture* tex;
    LBTexture* instantGradient;
    LBTexture* baby;
    LBTexture* baby2;
    LBTexture* bigben;
    LBTexture* country;
    
    LBFramebuffer *frameBuffer;
    
    LBFilter* filter;
    LBEffect1Filter* effect1Filter;
    LBEffect2Filter* effect2Filter;
    LBEffect3Filter* effect3Filter;
    LBEffect4Filter* effect4Filter;
    LBEffect5Filter* effect5Filter;
    LBEffect6Filter* effect6Filter;
    LBEffect7Filter* effect7Filter;
    LBEffect8Filter* effect8Filter;
    LBEffect9Filter* effect9Filter;
    LBGreyscaleFilter* greyScaleFilter;
    LBSepiaFilter* sepiaFilter;
    LBWhiteBalanceFilter* whiteBalanceFilter;
    LBMonoChromeFilter* monoChromeFilter;
    LBSharpenFilter* sharpenFilter;
    LBBoxBlurFilter* boxBlurFilter;
    LBBoxBlurFilter* boxBlurFilter2;
    LBRenderToScreenFilter* toScreenFilter;
    LBAdaptiveThresholdFilter* adaptiveFilter;
    LBProFilter* proFilter;
    LBVintageLowFilter* vintageLowFilter;
    LBInstantEffectFilter* instantEffectFilter;
    LBAnsenEffectFilter* ansenEffectFilter;
    LBRadialGradientFilter* radialGradientFilter;
}
@property (strong, nonatomic) EAGLContext *context;
@property (strong, nonatomic) GLKBaseEffect *effect;

- (void)setupGL;
- (void)tearDownGL;
@end

@implementation OpenGLViewController

@synthesize context = _context;
@synthesize effect = _effect;

- (void)viewportX: (int)x y:(int)y width:(int) width height:(int) height andScreenSizeWidth:(int) widthScreen screenSizeHeight:(int)heightScreen{
    LBGraphics::getInstance()->setScreenSizeAndViewportInRealDevice(widthScreen, heightScreen, x, y, width, height);
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

    if (!self.context) {
        NSLog(@"Failed to create ES context");
    }
    
    GLKView *view = (GLKView *)self.view;
    view.context = self.context;
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
    
    [self setupGL];
}

- (void)viewDidUnload
{    
    [super viewDidUnload];
    
    [self tearDownGL];
    
    if ([EAGLContext currentContext] == self.context) {
        [EAGLContext setCurrentContext:nil];
    }
	self.context = nil;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc. that aren't in use.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
    } else {
        return YES;
    }
}

- (void)setupGL
{
    [EAGLContext setCurrentContext:self.context];
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glDisable(GL_DEPTH_TEST);
    
    /*** need ***/
    LBGraphics* g = LBGraphics::getInstance();
    g->init();
     /*** END need ***/
    
    ocImg = [[OCImage alloc] initWithFileName32bit:@"baby2.png"];
    baby2 = new LBTexture([ocImg imageData], [ocImg width], [ocImg height]);
    baby2->setLocationAndScale(0.0f, 0.0f, 1.0f, 1.0f);
    [ocImg release];
    
    ocImg = [[OCImage alloc] initWithFileName32bit:@"baby.png"];
    baby = new LBTexture([ocImg imageData], [ocImg width], [ocImg height]);
    baby->setLocationAndScale(0.0f, 0.0f, 1.0f, 1.0f);
    [ocImg release];
    
    ocImg = [[OCImage alloc] initWithFileName32bit:@"country.png"];
    country = new LBTexture([ocImg imageData], [ocImg width], [ocImg height]);
    country->setLocationAndScale(0.0f, 0.0f, 1.0f, 1.0f);
    [ocImg release];
    
    ocImg = [[OCImage alloc] initWithFileName32bit:@"bigben.png"];
    bigben = new LBTexture([ocImg imageData], [ocImg width], [ocImg height]);
    bigben->setLocationAndScale(0.0f, 0.0f, 1.0f, 1.0f);
    [ocImg release];
    
    ocImg = [[OCImage alloc] initWithFileName32bit:@"instant_gradient.png"];
    instantGradient = new LBTexture([ocImg imageData], [ocImg width], [ocImg height], GL_RGBA);
    instantGradient->setLocationAndScale(0.0f, 0.0f, 1.0f, 1.0f);
    [ocImg release];
    
    effect2Filter = new LBEffect2Filter();
    effect3Filter = new LBEffect3Filter();
    effect5Filter = new LBEffect5Filter();
    effect6Filter = new LBEffect6Filter();
    effect7Filter = new LBEffect7Filter();
    effect8Filter = new LBEffect8Filter();
    effect9Filter = new LBEffect9Filter();
    greyScaleFilter = new LBGreyscaleFilter();
    sepiaFilter = new LBSepiaFilter();
    whiteBalanceFilter = new LBWhiteBalanceFilter();
    whiteBalanceFilter->temperature(3000);
    monoChromeFilter = new LBMonoChromeFilter();
    monoChromeFilter->setFilterColor(0.7, 0.7, 0.2);
    sharpenFilter = new LBSharpenFilter();
    sharpenFilter->setupFilterForSize(320, 480);
    sharpenFilter->setSharpness(4.0);
    toScreenFilter = new LBRenderToScreenFilter();
    adaptiveFilter = new LBAdaptiveThresholdFilter();
    proFilter = new LBProFilter();
    instantEffectFilter = new LBInstantEffectFilter();
    vintageLowFilter = new LBVintageLowFilter();
    ansenEffectFilter = new LBAnsenEffectFilter();
    radialGradientFilter = new LBRadialGradientFilter();
    radialGradientFilter->setOpacity(0.4f);
    
    [self texture:0];
    [self effect:0];
    
}

- (void)tearDownGL
{
    [EAGLContext setCurrentContext:self.context];
    deleteSingleton();
    DELETE_SAFELY(tex);
    DELETE_SAFELY(filter);
}

#pragma mark - GLKView and GLKViewController delegate methods

- (void)update
{
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{	
    /*** require ***/
    [view bindDrawable];
    GLint defFBO;
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defFBO);
    LBGraphics::getInstance()->setDefaulFrameBuffer(defFBO);
    /*** END require ***/
    
    
    LBGraphics* g = LBGraphics::getInstance();
    g->renderToScreen();
    g->clear(1.0f, 0.0f, 0.0f);

    /*if(filter != 0){
        filter->setLocationAndScale(0, 60, 1.0f, 1.0f);
        filter->render();
    }
    else{
        tex->setLocation(0, 60);
        tex->renderUseDefaultProgram();
    }*/
        
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    
}

- (void) effect:(int) index{
    
    switch (index) {
        case 0:
            filter = ansenEffectFilter;
            break;
        case 1:
            filter = effect3Filter;
            break;
        case 2:
            filter = effect2Filter;
            break;
        case 3:
            filter = effect7Filter;
            break;
        case 4:
            filter = effect6Filter;
            break;
        case 5:
            filter = effect5Filter;
            break;
        case 6:
            filter = effect8Filter;
            break;
        case 7:
            filter = greyScaleFilter;
            break;
        case 8:
            filter = sepiaFilter;
            break;
        case 9:
            filter = effect9Filter;
            break;
        case 10:
            filter = 0;
            break;
        case 11:
            filter = whiteBalanceFilter;
            break;
        case 12:
            filter = monoChromeFilter;
            break;
        case 13:
            filter = sharpenFilter;
            break;
        case 14:
            filter = adaptiveFilter;
            break;
        case 15:
            filter = proFilter;
            break;
        case 16:
            filter = vintageLowFilter;
            break;
        case 17:
            filter = instantEffectFilter;
            break;
        case 18:
            filter = ansenEffectFilter;
            break;
    }
    if(filter != 0){
        [self setTexture];
        filter->addTarget(radialGradientFilter);
        radialGradientFilter->addTarget(toScreenFilter);
    }
}

-(void) setTexture{
    if(filter != 0){
        filter->setTexture(tex);
        if(filter == instantEffectFilter) instantEffectFilter->setBlendTexture(instantGradient, tex->getWidth(), tex->getHeight());
    }
    else{
        printf("ViewController - setTexture - Please set filter before");
    }
}

- (void) texture:(int) index{
    switch (index) {
        case 0:
            tex = baby;
            break;
        case 1:
            tex = baby2;
            break;
        case 2:
            tex = country;
            break;
        case 3:
            tex = bigben;
            break;
        default:
            break;
    }
    [self setTexture];
}
@end